package com.learm.socket.pool_v2;

import java.lang.reflect.*;
import java.util.Properties;

import org.apache.log4j.Logger;

/**
 * <p>
 * Title: 连接管理器
 * </p>
 *
 * <p>
 * Description:
 * </p>
 *
 * <p>
 * Copyright: 融博技术有限公司 2012
 * </p>
 *
 * @author 袁泉锋HO174959
 * @version 1.0
 * @date Oct 15, 2012
 *
 */
public class SocketConnectionManager {
    private static final Logger logger = Logger.getLogger("FrameLog");
    //测试程序默认的连接池实现类
    public static final String PROVIDER_CLASS = "com.rb.socketpool.MyConnectionProvider";
    //测试程序的默认ip
    public static final String HOST = "127.0.0.1";
    //测试程序的默认端口号
    public static final String PORT = "9880";
    /**
     *   注册钩子程序的静态匿名块,jvm退出的前一刻，调用ShutdownThread线程
     */
    static {
        Runtime runtime = Runtime.getRuntime();
        Class c = runtime.getClass();
        try {
            Method m = c.getMethod("addShutdownHook",
                    new Class[] { Thread.class });
            m.invoke(runtime, new Object[] { new ShutdownThread() });
        } catch (NoSuchMethodException e) {
            logger.error(e.getMessage());
            e.fillInStackTrace();
        } catch (Exception e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     *   默认的构造函数
     */
    public SocketConnectionManager() {
    }

    /**
     * <Description> 得到并初始化一个连接池
     *   连接池的实现类通过系统参数来传递进来，通过命令行-DConnectionProvider=YourImplClass
     *   如果没有指定的实现的话，则采用系统默认的实现类
     *   通过命令行传入的参数列表如下
     *   对方主机名-DHost=192.168.0.200
     *   对方端口号　-DPort=9880
     *   最小连接数     -DMax_size=10
     *   最大连结数　-DMin_size=20
     *   以上的值可以改变，但是参数不能改变，
     *   最大连结数和最小连接数可以省略，默认值分别为２０和１０
     *
     * @since Oct 15, 2012
     * @return
     * @throws Exception <Description>
     *
     */
    public static SocketConnectionPoolInterface getConnectionProvider() throws Exception {
        String provider_class = System.getProperty("ConnectionProvider");
        if (provider_class == null){
            provider_class = PROVIDER_CLASS;
        }
        String host = System.getProperty("Host");
        if (host == null){
            host = HOST;
        }
        String port = System.getProperty("port");
        if (port == null){
            port = PORT;
        }
        String max_size = System.getProperty("Max_size");
        String min_size = System.getProperty("Min_size");

        Properties pro = new Properties();
        pro.setProperty(SocketConnectionPoolInterface.SERVER_IP, host);
        pro.setProperty(SocketConnectionPoolInterface.SERVER_PORT, port);
        if (max_size != null) {
            pro.setProperty(SocketConnectionPoolInterface.MAX_SIZE, max_size);
        }
        if (min_size != null) {
            pro.setProperty(SocketConnectionPoolInterface.MIN_SIZE, min_size);
        }
        //通过反射得到实现类
        logger.info("Provider_class:" + provider_class);
        Class provider_impl = Class.forName(provider_class);
        //由于是单子模式，采用静态方法回调
        Method m = provider_impl.getMethod("newInstance",
                new Class[] { java.util.Properties.class });
        SocketConnectionPoolInterface provider = null;
        try {
            provider = (SocketConnectionPoolInterface) m.invoke(provider_impl,
                    new Object[] { pro });
        } catch (Exception e) {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return provider;
    }

    /**
     *
     *   <p> 一个钩子的线程:   在程序结束的时候调用注销连接池 </p>
     *   <p> Description:   </p>
     *   <p> Copyright:   Copyright   Tarena(c)   2005 </p>
     *   <p> Company:   Tarena </p>
     *   @author   chengxing
     *   @version   1.0
     */
    private static class ShutdownThread extends Thread {
        public void run() {
            try {
                SocketConnectionPoolInterface provider = SocketConnectionManager
                        .getConnectionProvider();
                if (provider != null) {
                    provider.destroy();
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
                e.printStackTrace();
            }
        }
    }

}
